// GPSClock.cpp : Defines the entry point for the application.
//

#include "windows.h"
#include "aygshell.h"
#include "winnls.h"

#include "GPSClock.h"
#include "GPS.h"

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

#define TIMER_BITMAP 1
#define TIMER_POLL_GPS 2

static SYSTEMTIME currentGPSTime;

INT_PTR CALLBACK GPSClockDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HBITMAP hbmpGPS;
	static HBITMAP hbmpClock;

    switch (message)
    {
        case WM_INITDIALOG:
            {
				hbmpGPS = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_GPS));
				hbmpClock = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_CLOCK));

                // Create a Done button and size it.  
                SHINITDLGINFO shidi;
				SHMENUBARINFO mbi;

                shidi.dwMask = SHIDIM_FLAGS;
                shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN;
                shidi.hDlg = hDlg;
                SHInitDialog(&shidi);

				// Create a menu bar
                memset(&mbi, 0, sizeof(SHMENUBARINFO));
				mbi.cbSize     = sizeof(SHMENUBARINFO);
				mbi.hwndParent = hDlg;
				mbi.nToolBarId = IDR_MENU;
				mbi.hInstRes   = GetModuleHandle(NULL);
				mbi.dwFlags = SHCMBF_HMENU;
	            SHCreateMenuBar(&mbi);

				// Change the headers to use a bold font
				LOGFONT lf;
				memset(&lf, 0, sizeof(LOGFONT));
				HDC hdc = GetDC(NULL);
				lf.lfHeight = -9 * GetDeviceCaps(hdc, LOGPIXELSY) / 72;
				ReleaseDC(NULL, hdc);
				lf.lfWeight = FW_BOLD;
				HFONT hFont = CreateFontIndirect(&lf);

				SendDlgItemMessage(hDlg, IDC_LABEL_DEVICE, WM_SETFONT, (WPARAM)hFont, 0);
				SendDlgItemMessage(hDlg, IDC_LABEL_GPS, WM_SETFONT, (WPARAM)hFont, 0);

				// Disable the Update soft key until we get
				// a valid fix from the GPS
				SHEnableSoftkey(SHFindMenuBar(hDlg), IDM_UPDATE, FALSE, FALSE);

				// Start two timers to update the display. The
				// first toggles the bitmap displayed at the bottom
				// while the second polls the GPS for updated data
				SetTimer(hDlg, TIMER_BITMAP, 5000, NULL);
				SetTimer(hDlg, TIMER_POLL_GPS, 100, NULL);

				// Pretend the user selected the Start GPS menu item
				// so that the application starts off with the GPS
				// enabled
				SendMessage(hDlg, WM_COMMAND, IDM_GPS_START, 0);
            }
            return (INT_PTR)TRUE;

		case WM_INITMENUPOPUP:
			// The menu is about to popup so enable/disable
			// the various menu items depending upon the state
			// of the application.
			if (GPS_IsOpened())
			{
				EnableMenuItem((HMENU)wParam, IDM_GPS_START, MF_BYCOMMAND | MF_GRAYED);
				EnableMenuItem((HMENU)wParam, IDM_GPS_STOP,  MF_BYCOMMAND | MF_ENABLED);
			}
			else
			{
				EnableMenuItem((HMENU)wParam, IDM_GPS_START, MF_BYCOMMAND | MF_ENABLED);
				EnableMenuItem((HMENU)wParam, IDM_GPS_STOP,  MF_BYCOMMAND | MF_GRAYED);
			}
			break;

        case WM_COMMAND:
            switch (LOWORD(wParam))
			{
				case IDOK:
		            EndDialog(hDlg, LOWORD(wParam));
					return (INT_PTR)TRUE;

				case IDM_GPS_START:
					if (!GPS_IsOpened())
					{
						GPS_Open();
					}
					break;
           
				case IDM_GPS_STOP:
					if (GPS_IsOpened())
					{
						GPS_Close();

						// Disable the clock update button again as
						// we've stopped receiving updates from the GPS
						SHEnableSoftkey(SHFindMenuBar(hDlg), IDM_UPDATE, FALSE, FALSE);
					}
					break;

				case IDM_UPDATE:
					if (MessageBox(hDlg, _T("Are you sure you wish to update your device time with your gps time?"), _T("Alert!"), MB_YESNO | MB_ICONASTERISK) == IDYES)
					{
						// Update the system clock with the
						// current time from the GPS
						SetSystemTime(&currentGPSTime);
					}
					break;
			}
            break;

		case WM_TIMER:
			// Determine which timer triggered
			if (wParam == TIMER_BITMAP)
			{
				// Toggle the image displayed at
				// the bottom of the dialog
				HBITMAP hbmp = hbmpClock;
				if ((HBITMAP)SendDlgItemMessage(hDlg, IDC_GPS_IMAGE, STM_GETIMAGE, 0, 0) == hbmpClock)
					hbmp = hbmpGPS;

				SendDlgItemMessage(hDlg, IDC_GPS_IMAGE, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hbmp);
			}
			else if (wParam == TIMER_POLL_GPS)
			{
				// Update displayed device date and time
				SYSTEMTIME st;
				TCHAR szBuffer[2048];

				GetLocalTime(&st);

				GetDateFormat(GetUserDefaultLCID(), DATE_LONGDATE, &st, NULL, szBuffer, ARRAY_SIZE(szBuffer));
				SetDlgItemText(hDlg, IDC_DEVICE_DATE, szBuffer);

				GetTimeFormat(GetUserDefaultLCID(), 0, &st, NULL, szBuffer, ARRAY_SIZE(szBuffer));
				SetDlgItemText(hDlg, IDC_DEVICE_TIME, szBuffer);

				// Update displayed GPS date and time
				if (GPS_DataHasChanged())
				{
					// Get the current GPS location information
					GPS_POSITION pos;
					GPS_GetData(&pos, NULL);

					if (pos.dwValidFields & GPS_VALID_UTC_TIME)
					{
						FILETIME ftUTC, ftLocal;

						// We have a valid time update from the
						// GPS so enable the 'Update' softkey
						SHEnableSoftkey(SHFindMenuBar(hDlg), IDM_UPDATE, FALSE, TRUE);

						// Store the current UTC date/time for
						// later use
						currentGPSTime = pos.stUTCTime;

						// Convert the UTC time into the local time zone
						SystemTimeToFileTime(&pos.stUTCTime, &ftUTC);
						FileTimeToLocalFileTime(&ftUTC, &ftLocal);
						FileTimeToSystemTime(&ftLocal, &st);
						
						// Update the display with the current date/time
						GetDateFormat(GetUserDefaultLCID(), DATE_LONGDATE, &st, NULL, szBuffer, ARRAY_SIZE(szBuffer));
						SetDlgItemText(hDlg, IDC_GPS_DATE, szBuffer);

						GetTimeFormat(GetUserDefaultLCID(), 0, &st, NULL, szBuffer, ARRAY_SIZE(szBuffer));
						SetDlgItemText(hDlg, IDC_GPS_TIME, szBuffer);
					}
				}
			}
			break;

        case WM_CLOSE:
			KillTimer(hDlg, TIMER_BITMAP);
			KillTimer(hDlg, TIMER_POLL_GPS);

			if (GPS_IsOpened())
			{
				GPS_Close();
			}

            return (INT_PTR)TRUE;
    }
    return (INT_PTR)FALSE;
}

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPTSTR    lpCmdLine,
                   int       nCmdShow)
{
	return DialogBox(hInstance, (LPCTSTR)IDD_GPSCLOCK, NULL, GPSClockDialog);
}